<template>
  <div class="input-file">
    <input type="file" class="input-file__input" @change="handleUpload" v-bind="inputAttr" />
    <slot name="input-before"></slot>
    <slot name="input">
      <el-button type="primary" icon="upload">点击上传</el-button>
    </slot>
    <slot name="input-after"></slot>

    <div class="input-file__tip" v-if="tips">{{ tips }}</div>
  </div>
</template>

<script setup>
// import axios from 'axios'
import { ElMessage } from 'element-plus'
import { http } from 'jax-node'

const emits = defineEmits(['update:modelValue'])
const props = defineProps({
  modelValue: Array, // v-model
  tips: String, // tips

  inputAttr: Object, // input原生属性

  limit: 0, // 上传数量 0、不限制

  fieldname: { type: String, default: 'files' }, // 上传文件的字段名

  url: { type: String, default: '/upload' }, // 上传地址

  headers: { type: Object, default: {} }, // header

  loading: { default: '上传中...' }, // 上传提示

  beforeUpload: Function, // 上传前
  uploadProgress: Function, // 上传过程中
  uploadSuccess: Function, // 上传成功
})

let fileId = 0
const fileList = ref([])

watch(
  () => props.modelValue,
  () => init()
)

const multiple = computed(() => {
  return props.inputAttr && props.inputAttr.multiple
})

const init = () => {
  fileList.value = props.modelValue || []
}

const handleUpload = (e) => {
  upload(e.target.files)

  // 解决连续选择同一个文件
  e.target.value = null
}

const upload = (files) => {
  const { limit } = props

  if (limit && files.length + fileList.value.length > limit) {
    return ElMessage.error(`最多上传${limit}个文件`)
  }

  for (let i = 0; i < files.length; i++) {
    send(files[i])
  }
}

const send = (file) => {
  const formData = new FormData()

  formData.append(props.fieldname, file)

  // 上传前
  if (props.beforeUpload) {
    var result = props.beforeUpload(file)
    if (result == false) return
  }

  //   let config = {
  //     headers: { 'Content-Type': 'multipart/form-data' },
  //     showLoading: '上传中...',
  //   };

  const returnFile = {
    index: fileId++,
    status: 'ready',
    name: file.name,
    size: file.size,
    percentage: 0,
    file: window.URL.createObjectURL(file),
  }

  // 支持文件多选
  if (multiple.value) {
    const data = fileList.value
    data.push(returnFile)
    emits('update:modelValue', data)
  } else {
    emits('update:modelValue', [returnFile])
  }

  const fileIndex = fileList.value && fileList.value.length ? fileList.value.length - 1 : 0

  http({
    method: 'post',
    url: props.url,
    data: formData,
    onUploadProgress: (progressEvent) => {
      const percentage = ((progressEvent.loaded / progressEvent.total) * 100).toFixed(2)

      updateFiles(fileIndex, {
        percentage: percentage > 99 ? 99 : percentage,
        status: 'uploading',
      })

      props.uploadProgress && props.uploadProgress(progressEvent)
    },
    headers: props.headers,
    // showLoading: props.loading,
    // headers: { 'Content-Type': 'multipart/form-data' },
  })
    .then((res) => {
      updateFiles(fileIndex, {
        ...res[0],
        percentage: 100,
        status: 'success',
      })

      // 上传完成
      props.uploadSuccess && props.uploadSuccess(res)
    })
    .catch((error) => {
      updateFiles(fileIndex, {
        status: 'fail',
        error: error,
        percentage: 100,
      })
    })
}

// 更新上传文件信息
const updateFiles = (fileIndex, data) => {
  const newFileList = [...fileList.value]
  newFileList[fileIndex] = {
    ...fileList.value[fileIndex],
    ...data,
  }

  emits('update:modelValue', newFileList)
}
</script>

<style scoped lang="scss">
.input-file {
  position: relative;
  width: fit-content;
}

.input-file__input {
  position: absolute;
  top: 0;
  left: 0;
  opacity: 0;
  height: 100%;
  width: 100%;
  z-index: 1;
  cursor: pointer;
}

.input-file__tip {
  font-size: 12px;
  color: #999;
}
</style>
